/**
 * 项目名称（软件名称）：忠旺机械物资管理系统(mms)
 * 研发设计单位：忠旺机械设备制造有限公司机械设计院智能控制设计科设计与研发。
 * 版权所有：忠旺机械设备制造有限公司
 * 注：本项目的一切技术专利，使用规范归解释权由忠旺机械设备制造有限公司所有。
 * 软件版本：Ver 1.0.0
 * 文件路径：com.zhongwang.mms.module.purchase.service
 * 创建时间：2020年03月16日 14时06分
 **/
package com.zhongwang.mms.module.jiaGongStorage.service;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import com.zhongwang.mms.common.JsonResult;
import com.zhongwang.mms.gen.entity.*;
import com.zhongwang.mms.module.basic.dao.TCostDao;
import com.zhongwang.mms.module.basic.dao.TWarehouseInfoDao;
import com.zhongwang.mms.module.basic.service.BoardService;
import com.zhongwang.mms.module.jiaGongStorage.dao.StorageInDao;
import com.zhongwang.mms.module.jiaGongStorage.model.JInStorage;
import com.zhongwang.mms.module.jiaGongStorage.model.JStorage;
import com.zhongwang.mms.module.jiaGongStorage.model.JStorageDetail;
import com.zhongwang.mms.module.jiaGongStorage.model.JStorageInventory;
import com.zhongwang.mms.module.purchase.constant.PurchaseOrderType;
import com.zhongwang.mms.module.purchase.dao.*;
import com.zhongwang.mms.module.purchase.excelListener.PurWarInManageListener;
import com.zhongwang.mms.module.purchase.model.PInModel;
import com.zhongwang.mms.module.system.log.LogService;
import com.zhongwang.mms.util.PurchaseUtil;
import com.zhongwang.mms.util.ShiroUtils;
import com.zhongwang.mms.util.StringUtils;
import lombok.extern.log4j.Log4j2;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName： PurWarInManageService
 * @Description：甲供件 入库单业务逻辑层
 * @Author： 李青雨
 * @Date： 2020/3/16 14:06
 * @Version： V1.0
 **/
@Log4j2
@Service
public class StorageInService {

    @Autowired
    private PurWarInManageDao purWarInManageDao;
    @Autowired
    private TWarehouseInfoDao tWarehouseInfoDao;
    @Autowired
    private PurPOrderDetailDao purPOrderDetailDao;
    @Autowired
    private PurPOrderDao purPOrderDao;
    @Autowired
    private PurPInventoryDao purPInventoryDao;
    @Autowired
    private StorageInDao storageInDao;
    @Autowired
    private LogService logService;
    @Autowired
    private PurTProjectDao purTProjectDao;
    @Autowired
    private BoardService boardService;
    @Autowired
    private TCostDao tCostDao;

    @Value("${user.upload.path}")
    private String uploadPath;
    String msg = "";

    /**
     * @FunctionName: uploadExcelFile
     * @Description: 导入入库单
     * @Author: 徐一贺
     * @CreateDate: 2020/3/16 14:10
     * @Phone: 18241927380
     * @Param: uploadExcelFile 上传的文件
     * @Return: String 返回结果
     * @Version: 1.0.0
     */
    public String uploadExcelFile(MultipartFile uploadExcelFile) {

        try {
            msg = "导入成功";
            PurchaseUtil purchaseUtil = new PurchaseUtil();
            String orderCode = purchaseUtil.getNewOrderCode(PurchaseOrderType.PRK);
            String odrCode = purWarInManageDao.findPOrderByOdrCode(orderCode);
            //插入主表数据
            POrder pOrder = new POrder();
            pOrder.setOdrType(1);
            pOrder.setOdrRedFlag(0);
            pOrder.setOdrDate(new Date());
            pOrder.setOdrTakePerson(ShiroUtils.getUser().getName());
            pOrder.setOdrRedFlag(0);
            pOrder.setOdrCode(orderCode);
            int pOdrId = purPOrderDao.insert(pOrder);
            EasyExcel.read(uploadExcelFile.getInputStream(), PInModel.class, new PurWarInManageListener(purWarInManageDao, purPOrderDetailDao, pOdrId, pinModels -> {
                if (pinModels != null && pinModels.size() > 0) {
                    msg = "导入失败";
                    // 导出异常Excel
                    exportErrorExcel(pinModels);
                }
            })).headRowNumber(3).sheet().doRead();

        } catch (Exception e) {
            msg = "导入失败";
            return msg;
        }
        return msg;
    }

    /**
     * @FunctionName: findLastJGJOrderCode
     * @Description: 获取入库编码数量
     * @Author: 李青雨
     * @CreateDate: 2020/3/17 14:17
     * @Phone: 18241927380
     * @Param:
     * @Return:
     * @Version:
     */
    public String findLastJGJOrderCode() {
        if (storageInDao.findPJGJrderCodeCount() == 0) {
            return "";
        }
        return storageInDao.findLastJGJOrderCode();
    }

    /**
     * @FunctionName: findLastPCKOrderCode
     * @Description: 获取最后出库的编码
     * @Author: 徐一贺
     * @CreateDate: 2020/3/17 14:17
     * @Phone: 18241927380
     * @Param:
     * @Return:
     * @Version:
     */
    public String findLastPCKOrderCode() {
        return purWarInManageDao.findLastPCKOrderCode();
    }


    /**
     * 异常数据导出到Excel
     */
    private void exportErrorExcel(List<PInModel> errorList) {

        if (errorList.size() <= 0) {
            return;
        }

        User user = (User) SecurityUtils.getSubject().getPrincipal();

        // 取得错误数据
        String path = uploadPath + user.getAccount() + "/";
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        path = path + "dailyError.xlsx";
        // 头的策略
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 10);
        headWriteCellStyle.setWriteFont(headWriteFont);

        // 内容的策略
        WriteCellStyle contentWriteCellStyle = new WriteCellStyle();

        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        HorizontalCellStyleStrategy horizontalCellStyleStrategy =
                new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);

        // 这里 需要指定写用哪个class去读，然后写到第一个sheet，名字为模板 然后文件流会自动关闭
        EasyExcel.write(path, PInModel.class).registerWriteHandler(horizontalCellStyleStrategy).sheet("模板")
                .doWrite(errorList);

    }

    /**
     * 判断文件是否存在
     *
     * @param url 文件URL
     * @return 是否存在
     */
    public boolean exist(String url) {
        int i = url.lastIndexOf("files/");
        String path = uploadPath + url.substring(i + 6);
        File file = new File(path);
        if (!file.exists()) {
            return false;
        }

        return true;
    }

    /**
     * @param orderCodeType
     * @FunctionName: getOrderCode
     * @Description: 获取最新的单据编码
     * @Author: 徐一贺
     * @CreateDate: 2020/3/23 7:55
     * @Phone: 18241927380
     * @Param: orderCodeType 单据编码类型 PRK是入库 PCK是出库
     * @Return: String 返回最新的编码
     * @Version: 1.0.0
     */
    public String getOrderCode(int orderCodeType) {
        String orderCode = "";
        if (orderCodeType == 3) {
            orderCode = generateJGJStorageCode();
        }
        return orderCode;
    }
    /**
     * @FunctionName: generateJGJStorageCode
     * @Description: 获取最新出甲供件库单编码
     * @设计思路： 1.判断年后两位+月+日与当前年月日是否相同，如果相同且流水号则在流水号上递增1。
     * 2.如果数据为空则按照以JGJ+年（后两位）月日+001生成外购件出库单编码。
     * 3.如果不相同则按照以PRK+年（后两位）月日+001生成外购件出库单编码。
     * @Author: 徐一贺
     * @CreateDate: 2020/3/17 14:22
     * @Phone: 18241927380
     * @Param:
     * @Return: String 最新出库单编码
     * @Version:
     */
    private String generateJGJStorageCode() {
        String newGeneratePRKOrderCode = "";
        //获取最后编码
        String lastPRKOrderCode = findLastJGJOrderCode();
        //获取当前时间简码
        String datetimeCode = new SimpleDateFormat("yyMMdd").format(new Date());
        Integer sn = 0;
        if (lastPRKOrderCode.length() > 0) {
            //获取外购件库最新最后的入库单号
            sn = Integer.parseInt(lastPRKOrderCode.substring(9));
        }

        if (lastPRKOrderCode.length() == 0) {
            newGeneratePRKOrderCode = "JGJ" + new SimpleDateFormat("yyMMdd").format(new Date()) + "001";
        } else if (!lastPRKOrderCode.substring(3, 9).equals(datetimeCode)) {
            newGeneratePRKOrderCode = "JGJ" + new SimpleDateFormat("yyMMdd").format(new Date()) + "001";
        } else {
            newGeneratePRKOrderCode = "JGJ" + new SimpleDateFormat("yyMMdd").format(new Date()) + String.format("%03d", (sn + 1));
        }
        return newGeneratePRKOrderCode;
    }


    /**
     * @FunctionName: create
     * @Description: 创建入库单
     * @Author: 徐一贺
     * @CreateDate: 2020/3/23 10:46
     * @Phone: 18241927380
     * @Param: [pInOrder] 入库数据
     * @Return: com.zhongwang.mms.common.JsonResult 返回结果
     * @Version: 1.0.0
     */
    @Transactional(rollbackFor = Exception.class)
    public JsonResult create(JInStorage jInStorage) {
        //验证
        JsonResult jsonResult = new JsonResult();

        List<String> result = new ArrayList<>();
        for (int i = 0; i < jInStorage.getInsertData().size(); i++) {
            if (jInStorage.getInsertData().get(i).getOdaMatDesc() == null || jInStorage.getInsertData().get(i).getOdaMatDesc() == "") {
                result.add("\n第" + (i + 1) + "行" + " 物料描述 为空");
            }
            if (jInStorage.getInsertData().get(i).getOdaNum() == null || jInStorage.getInsertData().get(i).getOdaNum() <= 0) {
                result.add("\n第" + (i + 1) + "行" + " 数量为空或为负数 为空");
            }
            if (jInStorage.getInsertData().get(i).getOdaNumUnit() == null || jInStorage.getInsertData().get(i).getOdaNumUnit() == "") {
                result.add("\n第" + (i + 1) + "行" + " 单位为空 为空");
            }
            if (jInStorage.getInsertData().get(i).getOdaProCode() != null &&
                    jInStorage.getInsertData().get(i).getOdaProCode() != "") {
                if (boardService.isNotExist(boardService.projectCodeHandle(jInStorage.getInsertData().get(i).getOdaProCode()))) {
                    result.add("\n第" + (i + 1) + "行" + " 项目编码【" + jInStorage.getInsertData().get(i).getOdaProCode() + "】不存在 请修改");
                }
                if (StringUtils.isContainChinese(jInStorage.getInsertData().get(i).getOdaProCode())) {
                    result.add("\n第" + (i + 1) + "行" + " 项目编码不可出现汉字 违规字符");
                }
            }

            if (jInStorage.getInsertData().get(i).getWarehouseLocation() == null || jInStorage.getInsertData().get(i).getWarehouseLocation() == "") {
                result.add("\n第" + (i + 1) + "行" + " 仓库为空 为空");
            }
            if (jInStorage.getInsertData().get(i).getOdaItyStockType() == null || jInStorage.getInsertData().get(i).getOdaItyStockType() == "") {
                result.add("\n第" + (i + 1) + "行" + " 在库类型为空 为空");
            } else {
                if (!jInStorage.getInsertData().get(i).getOdaItyStockType().equals("库存在库") && !jInStorage.getInsertData().get(i).getOdaItyStockType().equals("项目在库")) {
                    result.add("\n第" + (i + 1) + "行" + " 入库类型不正确，应为“库存在库”或“项目在库”。");
                } else if (jInStorage.getInsertData().get(i).getOdaItyStockType().equals("项目在库")) {
                    if (jInStorage.getInsertData().get(i).getOdaProName() == null || jInStorage.getInsertData().get(i).getOdaProName() == "") {
                        result.add("\n第" + (i + 1) + "行" + " 项目文本为空 为空");
                    }
                    if (jInStorage.getInsertData().get(i).getOdaProCode() == null || jInStorage.getInsertData().get(i).getOdaProCode() == "") {
                        result.add("\n第" + (i + 1) + "行" + " 项目编码为空 为空");
                    }
                }
            }
        }
        if (!result.isEmpty()) {
            result.add("\n单据保存失败，请先维护以上外购件信息！");
            jsonResult.setData(result);
            jsonResult.setType(JsonResult.ResultType.ERROR);
            return jsonResult;
        }

        //创建主单数据
        JStorage jStorage = new JStorage();
        jStorage.setOdrCode(getOrderCode(3));
        jStorage.setOdrRemark(jInStorage.getFormData().getOdrRemark());
        jStorage.setOdrType(1);
        jStorage.setOdrRedFlag(0);
        jStorage.setOdrDate(new Date());
        jStorage.setOdrTakePerson(jInStorage.getFormData().getOdrTakePerson());
        jStorage.setOdrReqFlag(0);
        jStorage.setOdrChangeFlag(0);
        jStorage.setOdrMakeDate(new Date());
        jStorage.setOdrMakePersonId(ShiroUtils.getUser().getId());
        jStorage.setOdrDept(jInStorage.getFormData().getOdrDept());
        jStorage.setOdrOutType(jInStorage.getFormData().getOdrOutType());
        storageInDao.insert(jStorage);
        Integer odrId = jStorage.getOdrId();
        try {
            //创建明细单
            for (com.zhongwang.mms.module.jiaGongStorage.model.JStorageDetail jStorageDetailModel : jInStorage.getInsertData()) {
                if (null != jStorageDetailModel.getOdaTrackCode() && jStorageDetailModel.getOdaTrackCode().trim().replace("\\s", "").replace("\n", "").equals("000000")) {
                    jStorageDetailModel.setOdaTrackCode("");
                }
                JStorageDetail jStorageDetail = new JStorageDetail();
                jStorageDetail.setOdaType(1);
                jStorageDetail.setOdaOdrId(odrId);
                jStorageDetail.setOdaRedFlag(0);
                //20211013修改采购入库（营口机械备件）SAP编码当输入空格时处理后也同样允许导入，实际业务不允许为空。修改后允许为空，当不为空时处理空格与空串

                jStorageDetail.setOdaSapCode(StringUtils.replaceNbspToSpace(jStorageDetailModel.getOdaSapCode()));
                jStorageDetail.setOdaMatDesc(StringUtils.replaceNbspToSpace(jStorageDetailModel.getOdaMatDesc()));
                jStorageDetail.setOdaNum(jStorageDetailModel.getOdaNum());
                jStorageDetail.setOdaNumUnit(jStorageDetailModel.getOdaNumUnit());
//                jStorageDetail.setOdaTotalPrice(pOrderDetailModel.getOdaTotalPrice()); //单价
//                jStorageDetail.setOdaNumPrice(pOrderDetailModel.getOdaNumPrice());//金额

                jStorageDetail.setSupplier(jStorageDetailModel.getSupplier()); //供应商
                jStorageDetail.setContractNo(jStorageDetailModel.getContractNo());//合同编号
                jStorageDetail.setOdaTrackCode(jStorageDetailModel.getOdaTrackCode());
                jStorageDetail.setOdaBrand(jStorageDetailModel.getOdaBrand());
                if (jStorageDetailModel.getOdaProName() != null) {
                    jStorageDetail.setOdaProName(StringUtils.replaceNbspToSpace(jStorageDetailModel.getOdaProName()));
                }
                jStorageDetail.setOdaProCode(boardService.projectCodeHandle(jStorageDetailModel.getOdaProCode()));
                jStorageDetail.setOdaWhiId(tWarehouseInfoDao.findWarehouseInfoByCode(jStorageDetailModel.getWarehouseLocation()).getWhiId());
                jStorageDetail.setOdaPosition(jStorageDetailModel.getOdaPosition());
                if (jStorageDetailModel.getOdaBookkeepingDateWeb() != null && !jStorageDetailModel.getOdaBookkeepingDateWeb().equals("")) {
                    jStorageDetail.setOdaBookkeepingDate(new SimpleDateFormat("yyyy-MM-dd").parse(jStorageDetailModel.getOdaBookkeepingDateWeb().replace('/', '-')));
                }

                jStorageDetail.setOdaSpec(jStorageDetailModel.getOdaSpec());
                if (tCostDao.getTCostByCosProCode(jStorageDetail.getOdaProCode()) != null) {
                    jStorageDetail.setOdaStockType(1);
                } else if (jStorageDetailModel.getOdaItyStockType().equals("项目在库")) {
                    jStorageDetail.setOdaStockType(2);
                } else if (jStorageDetailModel.getOdaItyStockType().equals("库存在库")) {
                    jStorageDetail.setOdaStockType(1);
                }
                jStorageDetail.setOdaRemarkType(jStorageDetailModel.getOdaRemarkType());
                storageInDao.insertTStorageDetail(jStorageDetail);
                //检测库存表中是否有相同的数据
                JStorageInventory jStorageInventory = new JStorageInventory();
                jStorageInventory.setItyMatCode(jStorageDetail.getOdaMatCode());
                jStorageInventory.setItySapCode(jStorageDetail.getOdaSapCode());
                jStorageInventory.setItyMatDesc(jStorageDetail.getOdaMatDesc());
                jStorageInventory.setItyNum(jStorageDetail.getOdaNum());
                jStorageInventory.setItyAvaNum(jStorageDetail.getOdaNum());
                jStorageInventory.setItyNumUnit(jStorageDetail.getOdaNumUnit());
                jStorageInventory.setItyPrice(jStorageDetail.getOdaNumPrice());
                jStorageInventory.setItyTrackCode(jStorageDetail.getOdaTrackCode());
                jStorageInventory.setItyProName(jStorageDetail.getOdaProName());
                jStorageInventory.setItyProCode(jStorageDetail.getOdaProCode());
                jStorageInventory.setItyWhiId(jStorageDetail.getOdaWhiId());
                jStorageInventory.setItyPosition(jStorageDetail.getOdaPosition());
                jStorageInventory.setItyRemark(jStorageDetail.getOdaSpec());
                jStorageInventory.setItyBrand(jStorageDetail.getOdaBrand());
                jStorageInventory.setItyRowNo(jStorageDetail.getOdaId());
                jStorageInventory.setSupplier(jStorageDetail.getSupplier());
                jStorageInventory.setContractNo(jStorageDetail.getContractNo());
                if (tCostDao.getTCostByCosProCode(jStorageDetail.getOdaProCode()) != null) {
                    jStorageInventory.setItyStockType(1);
                } else if (jStorageDetailModel.getOdaItyStockType().equals("项目在库")) {
                    jStorageInventory.setItyStockType(2);
                } else if (jStorageDetailModel.getOdaItyStockType().equals("库存在库")) {
                    jStorageInventory.setItyStockType(1);
                }
                jStorageInventory.setItyBookkeepingDate(jStorageDetail.getOdaBookkeepingDate());
                jStorageInventory.setItyRemarkType(jStorageDetail.getOdaRemarkType());
                storageInDao.insertJStorageInventory(jStorageInventory);

            }
            result.add("单据保存成功！");
            jsonResult.setType(JsonResult.ResultType.SUCCESS);
            jsonResult.setData(result);
            //记录操作日志
            logService.saveLog("出入库操作-入库", "入库单据编码：" + jStorage.getOdrCode());
        } catch (Exception ex) {
            ex.printStackTrace();
            //记录异常错误日志信息
            log.error("【正式入库-异常日志】:异常入库单编码：" + jStorage.getOdrCode() + "{" + ex.getMessage() + "}");
            result.add("单据保存失败！");
            jsonResult.setData(result);
        }
        return jsonResult;

    }

    public List<TWarehouseInfo> findWarehouseInfoList() {
        return storageInDao.findWarehouseInfoList();
    }
}